package com.qf.springboottest.service.Impl;

import cn.hutool.core.io.resource.ResourceUtil;
import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil;
import cn.hutool.core.text.csv.CsvWriter;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.qf.springboottest.dao.UserDao;
import com.qf.springboottest.entity.User;
import com.qf.springboottest.ex.UserException;
import com.qf.springboottest.service.UserService;
import com.qf.springboottest.vo.UserRegistVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    UserDao userDao;

    @Value("${file.path}")
    String filepath;

    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public User login(String username, String password) {
        //1.根据用户名查询用户信息 得调用dao层的方法
        User user = userDao.getUserByName(username);

        if (user == null) {
            //没有匹配的用户,直接返回null
            return null;
        }else {
            //2.比对密码是否正确
            String dbpassword = user.getPassword();

            //转换password为 md5字符串
            String md5password = DigestUtil.md5Hex(password);

            if (dbpassword.equals(md5password)) {
                return user;
            }
            return null;
        }
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void registUser(UserRegistVo userRegistVo) throws IOException, UserException {

        //0.检查当前用户名是否存在 取用户输的用户名,再拿取到的用户名去和数据库里的用户名做比较
        String username = userRegistVo.getUsername();
        User dbuser = userDao.getUserByName(username);

        if (dbuser != null) {
            //用户名重复了 也可以抛自定义异常,比如前面的userException
            throw new UserException(-1001,"用户名重复了");
        }

        //1.保存文件到指定目录
        MultipartFile photo = userRegistVo.getPhoto();

        //生成一个唯一的文件名 为了避免文件重名 文件名前缀prefix
        String prefix = UUID.randomUUID().toString();
        //前缀+原文件名[用getOriginalFilename()方法] -->组合成一个唯一的文件名
        String fileName = prefix + "_" + photo.getOriginalFilename();

        //文件最终路径 使用配置文件的方式 里面写入路径
        String finalFilePath = filepath + fileName;

        //上传文件的方法 transferTo(对象)
        photo.transferTo(new File(finalFilePath));

        //可以通过日志判断前面写的代码是否执行成功
        log.debug("上传头像成功，finalFilePath={}",finalFilePath);

        //3.把用户的数据写入数据库表 需要依赖dao层
        User user = new User();
        user.setName(userRegistVo.getUsername());

        String password = userRegistVo.getPassword();
        //password转换成md5的password 使用hutool工具类中的DigestUtil
        String md5password = DigestUtil.md5Hex(password);
        user.setPassword(md5password);

        user.setSex(userRegistVo.getSex());

        user.setBirthday(userRegistVo.getDate());

        user.setRegistTime(new Date());

        //存文件名或完整的路径都可以
        user.setPhotopath(fileName);

        //定义一个添加以上所有注册信息到数据库的方法
        userDao.insertUser(user);

        //可以通过日志判断前面写的代码是否执行成功
        log.debug("用户数据落库成功,user={}",user);

    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addUser(User user) throws UserException {

        //1.判断用户名是否存在
        String uname = user.getName();
        User dbuser = userDao.getUserByName(uname);

        if (dbuser != null){
            throw new UserException(-1001,"用户名重复了");
        }

        //2.密码处理
        String md5Password = DigestUtil.md5Hex(user.getPassword());
        user.setPassword(md5Password);

        //3.落库
        userDao.insertUser(user);
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateUserById(User user) throws UserException {
        //1.判断user中是否有id
        Integer id = user.getId();
        if (id == null){
            throw new UserException(-1002,"修改用户没传id");
        }

        //判断密码是否被修改了
        String password = user.getPassword();
        User dbuser= userDao.getUserById(id);
        String dbpassword = dbuser.getPassword();

        if (!dbpassword.equals(password)) {
            //把密码md5
            String md5Password = DigestUtil.md5Hex(password);
            if (md5Password.equals(dbpassword)){
                //没改密码
                throw new UserException(-1003, "密码和原密码一致");
            }else {
                //写了新的密码 和原来的md5不一致了
                user.setPassword(md5Password);
            }
        }
        //2.更新用户数据
        userDao.updateUserById(user);
    }



    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importUsers(MultipartFile file) throws IOException {
        // 1. 接收csv文件
        String filename = UUID.randomUUID().toString()+".csv";

        String finalFilepath = filepath + filename;

        file.transferTo(new File(finalFilepath));

        // 2. 读取csv文件中的内容，转换为 List<User> 用hutool工具类的方法CsvUtil.getReader()创建reader对象
        CsvReader reader = CsvUtil.getReader();

        //假设csv文件在classpath目录下 hutool工具类的读取方法reader.read
        List<User> userList = reader.read(ResourceUtil.getUtf8Reader(finalFilepath), User.class);

        // 3. 批量插入user数据
        userDao.insertUserList(userList);
    }


    @Transactional(propagation = Propagation.SUPPORTS)
    @Override
    public String export() {

        //1.查询用户表的所有数据,生成一个list
        List<User> allUsers = userDao.getAllUsers();

        //生成csv文件的文件名
        String filename = UUID.randomUUID().toString() + ".csv";

        //得到最终csv文件的物理路径
        String finalFilePath = filepath + filename;

        //2.把list写入一个csv文件中 使用hutool工具类
        CsvWriter writer = CsvUtil.getWriter(finalFilePath, CharsetUtil.CHARSET_UTF_8);

        //3.返回生成的csv文件名
        writer.writeBeans(allUsers);

        return filename;
    }

}
